home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
PROGRAM
/
BCCAPP.ARJ
/
BATCH.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-09-15
|
11KB
|
504 lines
/*
*
* Edit Batch entries. Uses EDIT object as a parent Class
*
* (C) 1990 Vision Software
*
* $Id: batch.c 1.2003 91/05/06 14:23:40 pcalvin beta $
*
* Comments:
*
* This class allows the user to Add/Edit and Delete structures without
* the usual headaches. This class is a collection of various others
* EDIT handles the Field I/O. DATABASE handles the Record I/O. Not
* much to do but sit back and take the credit..
*
* Bugs:
*
* None documented
*/
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <io.h>
#include <stdhdr.h>
#include <adl.h>
#include <menu.h>
#include <dbase.h>
#include <edit.h>
#include <batch.h>
#include "lowlevel.h"
/*
* Strings used for the various run-time operations
*/
STATIC SZ szAskCreate = "Would you like to create this record?";
STATIC SZ szHlpCreate = "Press \"Y\" to create, \"N\" to abandon";
STATIC SZ szAskSave = "Would you like to save the changes?";
STATIC SZ szHlpSave = "Press \"Y\" to save this record, \"N\" to abandon changes";
STATIC SZ szAskDelete = "Delete this record, Are you sure?";
STATIC SZ szHlpDelete = "Press \"Y\" to delete record, \"N\" to abort";
STATIC SZ szHlpIndex = "Select key for record ordering";
INLINE VOID BATCH::PrepRecForRead()
{
if (pfnRead != Nil)
pfnRead(pdtb->PdbQuery());
}
INLINE VOID BATCH::PrepRecForWrite()
{
if (pfnWrite != Nil)
pfnWrite(pdtb->PdbQuery());
}
/*
* Must open the DATABASE ourselves. No problem
*/
BATCH::BATCH(DBASE *pdb,CCH cchRecord,SZ szFileName,SZ sz,FNPDB pfnR,FNPDB pfnW) : EDIT(fTrue,sz)
{
pdtb = new DATABASE(pdb,cchRecord,szFileName,fTrue);
fDeleteDatabase = fTrue;
fCreateRecord = fFalse;
pfnRead = pfnR;
pfnWrite = pfnW;
cmiMac = cmiNil;
pmiCurrent = pmiNil;
}
/*
* Database is already created. It will remain open after BATCH
*/
BATCH::BATCH(DATABASE &rdtbOriginal,SZ sz,FNPDB pfnR,FNPDB pfnW) : EDIT(fTrue,sz)
{
pdtb = &rdtbOriginal;
fDeleteDatabase = fFalse;
fCreateRecord = fFalse;
pfnRead = pfnR;
pfnWrite = pfnW;
cmiMac = cmiNil;
pmiCurrent = pmiNil;
}
/*
* Close the DATABASE if it was created
*/
BATCH::~BATCH()
{
if (fDeleteDatabase)
delete pdtb;
}
/*
* Initializes the read. Simply rewinds the DATABASE and calls
* EDIT.
*/
VOID BATCH::Read()
{
if (cmiMac > cmiNil)
Verify(FSelectCmi(cmiNil));
else
fCreateRecord = !pdtb->FFirst();
EDIT::Read();
}
/*
* Creates a field() that may be used to change the active
* index file within an edit..
*/
VOID BATCH::IndexSelector(ROW row,COL col,SZ szMsg,CENT cent,PENT pent,CENT centDefault)
{
Assert(centDefault < cent);
Assert(pent != pentNil);
CCH cch = CchFromCentPent(cent,pent);
Field(row,col,szMsg,szSelector,'X',cch,szHlpIndex,pent[centDefault].sz);
centIndex = cent;
pentIndex = pent;
pedIndex = PedQuery();
pedIndex->Adjust(BATCH::FSelect,this,fFalse);
}
/*
* Sets up an index field.
*/
BOOL BATCH::FCreateIndex(SZ szIndex,CID cid,PED ped)
{
AssertSz(cmiMac < cmiOpenMax,"Too many index files");
CMI cmi = cmiMac++;
SZ sz = pdtb->SzIndex(cid);
CCH cch = pdtb->CchIndex(cid);
/*
* Initialize index record, if there is a default string, copy that
* into the index address.
*/
pmiCurrent = &rgmiActive[cmi];
pmiCurrent->cid = cid;
pmiCurrent->szIndex = szIndex;
pmiCurrent->sz = sz;
pmiCurrent->cch = cch;
pmiCurrent->row = ped->RowEdit() - 2;
pmiCurrent->col = ped->ColLeft() - 1;
strncpy(pmiCurrent->szIndex,sz,cch);
/*
* And select this as the current index.
*/
return (FSelectCmi(cmiNil));
}
/*
* Hooks up an index field. CID must be valid or program will ASSERT
*/
VOID BATCH::Index(ROW row,COL col,CID cid,SZ szMessage,CHAR ch,SZ szHelp,SZ szDflt)
{
CCH cch = pdtb->CchIndex(cid);
SZ sz = pdtb->SzIndex(cid);
SZ szIndex = new CHAR[cch];
SZ szDefault = (szDflt == szNil) ? szIndex : szDflt;
Field(row,col,szMessage,szIndex,ch,cch,szHelp,szDefault);
PED ped = PedQuery();
ped->Adjust(BATCH::FChange,this,fFalse);
if (szDefault != szIndex)
strncpy(sz,szDefault,cch);
Verify(FCreateIndex(szIndex,cid,ped));
}
/*
* Sets up the index field for this batch
*/
VOID BATCH::Index(ROW row,COL col,SZ szFile,SZ szMessage,SZ sz,CHAR ch,CCH cch,SZ szHelp,SZ szDflt)
{
SZ szIndex = new CHAR[cch];
SZ szDefault = (szDflt == szNil) ? szIndex : szDflt;
Field(row,col,szMessage,szIndex,ch,cch,szHelp,szDefault);
PED ped = PedQuery();
ped->Adjust(BATCH::FChange,this,fFalse);
if (szDefault != szIndex)
strncpy(sz,szDefault,cch);
Verify(FCreateIndex(szIndex,pdtb->CidIndexOn(szFile,sz,cch),ped));
}
/*
* Copies all indexes to their temporary storage areas..
*/
VOID BATCH::SaveIndexes()
{
for (CMI cmi = cmiNil; cmi < cmiMac; cmi++)
{
strncpy(rgmiActive[cmi].szIndex,rgmiActive[cmi].sz,rgmiActive[cmi].cch);
}
}
/*
* Copies all indexes back from the temporary storage area..
*/
VOID BATCH::RestoreIndexes()
{
for (CMI cmi = cmiNil; cmi < cmiMac; cmi++)
{
strncpy(rgmiActive[cmi].sz,rgmiActive[cmi].szIndex,rgmiActive[cmi].cch);
}
}
/*
* Selects new index file.
*/
BOOL BATCH::FSelectCmi(CMI cmi)
{
BOOL fValid = fFalse;
if (cmi < cmiMac)
{
pmiCurrent = &rgmiActive[cmi];
Verify(pdtb->FIndexTo(pmiCurrent->cid));
/*
* If no records are available, clear the fields..
*/
if (pdtb->FFirst())
{
fCreateRecord = fFalse;
PrepRecForRead();
}
else
{
fCreateRecord = fTrue;
ClearFields();
}
strcpy(szSelector,pentIndex[cmi].sz);
SaveIndexes();
RedrawFields();
fValid = fTrue;
}
return (fValid);
}
/*
* If the current record was modified, AND the user wants it saved,
* do so, then clear the changed flags
*/
VOID BATCH::MaybeSaveCurrent()
{
if (FModified())
{
/*
* The field has been modified, must check if the record needs to be created
* as well as saved..
*/
if (fCreateRecord)
{
fCreateRecord = fFalse;
if (FAskSz(szAskCreate,szHlpCreate))
{
RestoreIndexes();
PrepRecForWrite();
Verify(pdtb->FCreate());
Verify(pdtb->FSave());
}
else
{
ClearFields();
}
}
else if (FAskSz(szAskSave,szHlpSave))
{
PrepRecForWrite();
Verify(pdtb->FSave());
}
}
/*
* Force "Unchanged" status.
*/
ForceNoChanges();
}
/*
* Asks if should Exit, continue or whatever
*/
BOOL BATCH::FExit(void)
{
/*
* Save if needed..
*/
MaybeSaveCurrent();
/*
* Normal exit procedure
*/
return (EDIT::FExit());
}
/*
* Some new functionality added to our EDIT keys.
*
* PgUp: Next record
* PgDn: Previous record
* Home: First record
* End: Last record
* Del: Delete current record
* Ins: Create record (Useful if creating duplicate key)
*/
BOOL BATCH::FHandleCd(CD cd)
{
BOOL fContinue = fTrue;
switch (cd)
{
case cdInsert:
if (pmiCurrent->szIndex[0] != chNil && FAskSz(szAskCreate,szHlpCreate))
{
RestoreIndexes();
PrepRecForWrite();
Verify(pdtb->FCreate());
ClearFields();
Rewind();
SaveIndexes();
RedrawFields();
Verify(pdtb->FSave());
}
break;
case cdHome:
/*
* Be sure to save any changes..
*/
MaybeSaveCurrent();
if (pdtb->FFirst())
{
PrepRecForRead();
SaveIndexes();
RedrawFields();
}
break;
case cdEnd:
/*
* Be sure to save any changes..
*/
MaybeSaveCurrent();
if (pdtb->FLast())
{
PrepRecForRead();
SaveIndexes();
RedrawFields();
}
break;
case cdPageUp:
/*
* Be sure to save any changes..
*/
MaybeSaveCurrent();
if (pdtb->FPrevious())
{
PrepRecForRead();
SaveIndexes();
RedrawFields();
}
break;
case cdPageDown:
/*
* Be sure to save any changes..
*/
MaybeSaveCurrent();
if (pdtb->FNext())
{
PrepRecForRead();
SaveIndexes();
RedrawFields();
}
break;
case cdDelete:
if (!fCreateRecord && FAskSz(szAskDelete,szHlpDelete))
{
fCreateRecord = !pdtb->FDelete();
PrepRecForRead();
Rewind();
SaveIndexes();
RedrawFields();
}
break;
default:
fContinue = EDIT::FHandleCd(cd);
}
return (fContinue);
}
/*
* Checks for a change in the current field. If changes are found
* Ask if save is wanted and attempt to edit the new Field..
* Because a non-static member function requires a "this" pointer, we
* make this a static member and pass the "this" pointer explicitly
*/
BOOL BATCH::FChange(SZ sz,VOID *pv)
{
BATCH *pvThis = (BATCH *)pv;
BOOL fContinue = fTrue;
if (pvThis->pmiCurrent->szIndex == sz)
{
/*
* Save record if needed
*/
pvThis->MaybeSaveCurrent();
/*
* If the key is empty, provide a finder. Otherwise, edit or create
* that key.
*/
if (*sz == chNil)
{
ROW row = pvThis->wndEdit.RowQuery() + pvThis->pmiCurrent->row;
COL col = pvThis->wndEdit.ColQuery() + pvThis->pmiCurrent->col;
/*
* Doesn't make sense to provide a finder, if there is nothing to find
* If no finder provided, answer with an error. We cannot have
* blank keys created..
*/
if (pvThis->pdtb->FFirst())
{
VSCROLL vscr(row,col,10,*pvThis->pdtb);
HELP help("Use cursor keys to select the desired record");
/*
* Supply finder to pick record, illegal entry if finder is ignored.
*/
if (vscr.CentGet() != centError)
{
pvThis->PrepRecForRead();
pvThis->SaveIndexes();
}
else
{
pvThis->ClearFields();
fContinue = fFalse;
}
}
else
{
fContinue = fFalse;
}
}
else if (pvThis->pdtb->FGotoSz(sz,fTrue))
{
pvThis->PrepRecForRead();
pvThis->SaveIndexes();
}
else
{
pvThis->fCreateRecord = fTrue;
pvThis->ClearFields();
}
/*
* Update display
*/
pvThis->RedrawFields();
}
return (fContinue);
}
/*
* Index selector. Used to provide finder if user wants to
* change indexes..
*/
BOOL BATCH::FSelect(SZ sz,VOID *pv)
{
BATCH *pvThis = (BATCH *)pv;
ROW row = pvThis->wndEdit.RowQuery() + pvThis->pedIndex->RowEdit() - 2;
COL col = pvThis->wndEdit.ColQuery() + pvThis->pedIndex->ColLeft() - 1;
POPUP pop(row,col,pvThis->centIndex,pvThis->pentIndex);
CENT cent = pop.CentGet();
return ((cent == centError) ? fFalse : pvThis->FSelectCmi(cent));
}